#include "sort.h"

DEFINE_CMP(char)
DEFINE_CMP(int8_t)
DEFINE_CMP(uint8_t)
DEFINE_CMP(int16_t)
DEFINE_CMP(uint16_t)
DEFINE_CMP(int32_t)
DEFINE_CMP(uint32_t)
DEFINE_CMP(long)
DEFINE_CMP(my_sort_ulong)
DEFINE_CMP(int64_t)
DEFINE_CMP(uint64_t)
DEFINE_CMP(float)
DEFINE_CMP(double)

static qsort_cmp_type     user_cmp_handler;
qsort_cmp_type  get_user_cmp_handler(void)
{
    return user_cmp_handler;
}

void set_user_cmp_handler(qsort_cmp_type    p_func)
{
    user_cmp_handler = p_func;
}





void bub_sort(void *first, size_t nelem, size_t width, qsort_cmp_type   cmp)
{
    unsigned char temp[width];


    for ( size_t i = 0; i < nelem - 1; i++ ){

        for ( size_t j = 0; j < nelem - 1 - i; j++ ){
            char *pj = (char *)( (size_t)first + width * j);
            char *pj_1 = (char *)( (size_t)first + width * (j + 1) );
            if(cmp){
//                if ( sort_data_in[j] > sort_data_in[j + 1] ) {
                if(cmp(pj, pj_1) == 1){
//                    SORT_SWAP(sort_data_in[j], sort_data_in[j + 1]);
                    memcpy(temp, pj, width);  \
                    memcpy(pj, pj_1, width );  \
                    memcpy(pj_1, temp, width );  \
                }
            }
        }
    }
}


bool is_sorted_$(void *first, void *last, size_t width, is_sorted_cmp_t     cmp)
{
    char *current = (char *)first;
    char *next = (char *)( (size_t)first + width);

    if(cmp == NULL){
        return false;
    }

    while( (size_t)next < (size_t)last){
        if( !cmp(current, next) ){
            return false;
        }

        current += width;
        next += width;
    }

    return true;
}



#define DEFINE_IS_SORTED_CMP(type)    \
bool cmp_is_sorted_##type(void * a, void * b)    \
{   \
    if(*(type*)a <= *(type*)b){  \
        return true;    \
    }   \
    return false;   \
}   \

DEFINE_IS_SORTED_CMP(char)
DEFINE_IS_SORTED_CMP(int8_t)
DEFINE_IS_SORTED_CMP(uint8_t)
DEFINE_IS_SORTED_CMP(int16_t)
DEFINE_IS_SORTED_CMP(uint16_t)
DEFINE_IS_SORTED_CMP(int32_t)
DEFINE_IS_SORTED_CMP(uint32_t)
DEFINE_IS_SORTED_CMP(long)
DEFINE_IS_SORTED_CMP(int64_t)
DEFINE_IS_SORTED_CMP(uint64_t)
DEFINE_IS_SORTED_CMP(float)
DEFINE_IS_SORTED_CMP(double)


